package com.example.BlockChain.utils;

import com.example.BlockChain.entity.TradeBodyPool;
import com.example.BlockChain.entity.TradeObject;
import com.example.BlockChain.entity.block.BlockDownLoad;
import com.example.BlockChain.entity.block.BlockFile;
import com.google.gson.Gson;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BlockBaseUtils {

    /**
     * 从区块下载对象生成交易池对象
     *
     * @param bdl BlockDownLoad 区块下载对象，包含区块文件字符串
     * @return TradeBodyPool 交易池对象，包含交易数据的 Map
     * @throws Exception 如果解析区块数据失败，抛出异常
     */
    public static TradeBodyPool genTbp(BlockDownLoad bdl) throws Exception {
        TradeBodyPool tbp = new TradeBodyPool();
        String blockFileStr = bdl.getBlockFileStr(); // 获取区块文件内容（JSON 字符串）
        tbp.setTbMap(genTbm(blockFileStr)); // 将区块字符串解析为交易 Map
        return tbp; // 返回交易池对象
    }

    /**
     * 将区块文件字符串解析为交易体 Map 对象
     *
     * @param blockFileStr 区块文件的 JSON 字符串表示
     * @return Map<String, TradeObject> 交易体 Map，键为交易 ID，值为交易体
     * @throws Exception 如果解析 JSON 或映射数据失败，抛出异常
     */
    public static Map<String, TradeObject> genTbm(String blockFileStr) throws Exception {
        Map<String, TradeObject> tbMap = new HashMap<>(); // 初始化交易 Map
        try {
            // 将 JSON 字符串反序列化为 BlockFile 对象
            BlockFile blockFile = new Gson().fromJson(blockFileStr, BlockFile.class);
            tbMap = blockFile.getTbMap(); // 从区块文件对象中获取交易体 Map
        } catch (Exception e) {
            // 捕获并抛出解析异常
            throw new Exception(e);
        }
        return tbMap; // 返回交易体 Map
    }

    /**
     * 将 Map 数据转为交易体对象
     *
     * @param map 包含交易数据的 Map，键为字段名，值为字段值
     * @return TradeObject 转换后的交易体对象
     */
    public static TradeObject mapToTradeBody(Map map) {
        TradeObject tb = null;
        try {
            tb = new TradeObject(); // 创建空的交易体对象
            Field[] fields = TradeObject.class.getDeclaredFields(); // 获取交易体类的所有字段
            for (Field field : fields) {
                field.setAccessible(true); // 设置字段可访问
                field.set(tb, map.get(field.getName())); // 从 Map 中获取对应字段值并赋值
            }
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
            // 捕获安全异常或访问异常
            e.printStackTrace();
        }
        return tb; // 返回交易体对象
    }

    /**
     * 将字符串列表转换为字节数组
     *
     * @param list 包含字符串的列表
     * @return byte[] 转换后的字节数组
     * @throws IOException 如果序列化失败，抛出 IO 异常
     */
    public static byte[] listToByteArray(List<String> list) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 创建字节流输出
        ObjectOutputStream oos = new ObjectOutputStream(bos); // 创建对象流输出
        oos.writeObject(list); // 将字符串列表写入对象流
        oos.flush(); // 刷新流
        return bos.toByteArray(); // 返回字节数组
    }

    /**
     * 泛型方法：将 Map 数据转换为指定类型的对象
     *
     * @param map 包含数据的 Map
     * @param clasz 目标类类型
     * @param <T> 泛型，目标类类型
     * @return T 转换后的目标类对象
     */
    public static <T> T mapToTrade(Map map, Class<T> clasz) {
        T tb = null;
        try {
            // 创建目标类实例
            tb = clasz.newInstance();
            Field[] fields = clasz.getDeclaredFields(); // 获取目标类的所有字段
            for (Field field : fields) {
                field.setAccessible(true); // 设置字段可访问
                field.set(tb, map.get(field.getName())); // 从 Map 中获取对应字段值并赋值
            }
        } catch (InstantiationException e) {
            e.getMessage(); // 捕获实例化异常
            return null;
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace(); // 捕获访问异常
        }
        return tb; // 返回目标类对象
    }
}

